﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using GsifWeb4.Models;
using GsifWeb4.ViewModels;
using System.Data.Common;

namespace GsifWeb4.Controllers
{
    public class MatchReportController : Controller
    {
        gsifdbEntities gsifDB = new gsifdbEntities();

        // Listar alla matcher för ett specifikt lag
        // GET: /MatchReport/
        public ActionResult Index(string team)
        {
            List<match_gsif> matches = (from match in gsifDB.match_gsif
                                        where match.Lag == team
                                        orderby match.Datum descending
                                        select match).ToList();

            return View("ShowMatches", matches);
        }

        // Hämtar all data för en specifik match och visar denna
        public ActionResult Details(int id)
        {
            // ViewModel to return
            MatchReportViewModel matchReportViewModel = new MatchReportViewModel();

            matchReportViewModel.Match = GetMatchInformation(id);

            // Loop over all players and set properties on viewmodel for each player
            SetMatchStatisticPerPlayer(id, matchReportViewModel);

            return View("Details", matchReportViewModel);
        }

        // Hämtar alla matcher för angivet år för att möjliggöra uppdatering av matchreferat
        public ActionResult ShowMatchesToEdit(int? year)
        {
            return View(new MatchesToEditViewModel(User.Identity.Name, gsifDB, year.HasValue ? year.Value : DateTime.Now.Year));
        }


        // Hämtar all data för en specifik match och visar denna för att kunna editera
        public ActionResult UpdateMatchReport(int id)
        {
            // ViewModel to return
            MatchReportViewModel matchReportViewModel = new MatchReportViewModel();

            matchReportViewModel.Match = GetMatchInformation(id);

            List<SelectPlayerItem> selectPlayerList = new List<SelectPlayerItem>();
            selectPlayerList = GetSelectablePlayers(matchReportViewModel.Match.Team);

            // List with all players that could be Man of the match
            List<SelectPlayerItem> momPlayerList = new List<SelectPlayerItem>();
            momPlayerList.Add(new SelectPlayerItem() { Id = -1, Text = "<-- Välj -->" });
            int currentManOfTheMatch = -1;

            // Loop over all players and set properties on viewmodel for each player
            SetMatchStatisticPerPlayer(id, matchReportViewModel);

            // Loop over each person and add list of potential players to select from and add it to list with man of the match players
            foreach (var matchStatPerson in matchReportViewModel.MatchStatistics)
            {
                // Skapa en selectList med alla spelare som kan väljas samt sätt denna som förvald
                matchStatPerson.AllPlayers = new SelectList(selectPlayerList, "Id", "Text", matchStatPerson.PlayerID);

                if (matchStatPerson.ManOftheMatch)
                    currentManOfTheMatch = matchStatPerson.PlayerID;

                // Add player to players that could be the man of the match
                momPlayerList.Add(new SelectPlayerItem() { Id = matchStatPerson.PlayerID, Text = matchStatPerson.FName + " " + matchStatPerson.EName });
            }

            // Markera nuvarande matchens lirare 
            matchReportViewModel.ManOfMatchPlayers = new SelectList(momPlayerList, "Id", "Text", currentManOfTheMatch);

            return View("UpdateMatchReport", matchReportViewModel);
        }

        private void SetMatchStatisticPerPlayer(int id, MatchReportViewModel matchReportViewModel)
        {
            matchReportViewModel.MatchStatistics = new List<MatchStatPerson>();

            var matchStats = (from stat in gsifDB.statistik_gsif
                              join player in gsifDB.laget_gsif on stat.SpId equals player.ID
                              where stat.StId == id
                              select new { Statistics = stat, player.FNamn, player.ENamn, player.BildLiten, player.ID }).ToList();

            foreach (var matchStat in matchStats)
            {
                MatchStatPerson matchStatPerson = new MatchStatPerson();
                matchStatPerson.FName = matchStat.FNamn;
                matchStatPerson.EName = matchStat.ENamn;
                matchStatPerson.ImagePathSmall = matchStat.BildLiten;
                matchStatPerson.PlayerID = matchStat.ID;
                matchStatPerson.Position = (int)matchStat.Statistics.Typ.Value;
                matchStatPerson.YellowCards = matchStat.Statistics.Gula.HasValue ? matchStat.Statistics.Gula.Value : 0;
                matchStatPerson.RedCard = matchStat.Statistics.Roda.HasValue ? matchStat.Statistics.Roda.Value : 0;
                matchStatPerson.Goals = matchStat.Statistics.Mal.HasValue ? matchStat.Statistics.Mal.Value : 0;
                matchStatPerson.Assists = matchStat.Statistics.Assist.HasValue ? matchStat.Statistics.Assist.Value : 0;
                matchStatPerson.ManOftheMatch = string.IsNullOrEmpty(matchStat.Statistics.ManOfMatch) ? false : true;

                matchReportViewModel.MatchStatistics.Add(matchStatPerson);
            }
        }

        private List<SelectPlayerItem> GetSelectablePlayers(string team)
        {
            List<laget_gsif> possiblePlayers = new List<laget_gsif>();

                // Hämta alla aktiva spelare
                possiblePlayers = (from players in gsifDB.laget_gsif
                                   where players.Inaktiv != InActivePlayer.InActive.DbValue
                                   select players).ToList();
                //select new SimplePlayer { Name = players.FNamn + " " + players.ENamn, Id = players.ID, Team = players.Lag }).ToList();

                if (Team.MenA.IsDbValue(team) || Team.MenC.IsDbValue(team))
                {
                    // Herrmatch. Hämta alla aktiva herrar
                    possiblePlayers = possiblePlayers.Where(p => p.Kon == Sex.Male.DbValue).ToList();
                }
                else if (Team.WomenA.IsDbValue(team) || Team.WomenB.IsDbValue(team))
                {
                    // Herrmatch. Hämta alla aktiva herrar
                    possiblePlayers = possiblePlayers.Where(p => p.Kon == Sex.Female.DbValue).ToList();
                }

            List<SelectPlayerItem> selectPlayerList = SortListAndAddDescriptionText(possiblePlayers);
            return selectPlayerList;
        }

        private MatchInfo GetMatchInformation(int id)
        {
            match_gsif selectedMatch = (from match in gsifDB.match_gsif
                                        where match.MaId == id
                                        select match).Single();

            MatchInfo matchInfo = new MatchInfo();
            matchInfo.Id = (int)selectedMatch.MaId;
            matchInfo.Date = selectedMatch.Datum.Value;
            matchInfo.MatchReport = HttpUtility.HtmlDecode(selectedMatch.Matchref);
            matchInfo.Opponent = selectedMatch.Motstandare;
            matchInfo.Place = selectedMatch.Plats;
            matchInfo.HomeGame = (selectedMatch.Plan.ToLower() == "h");
            matchInfo.MatchType = new SelectList(MatchType.AllStatuses.ToStringList(), Statuses.GetTextFromDbValue(MatchType.AllStatuses, selectedMatch.Typ));
            matchInfo.Round = selectedMatch.Omgang;
            matchInfo.Team = selectedMatch.Lag;

            // I databasen står resultat som 3-8 (0-3), där GSIFs mål alltid står först.
            if (!string.IsNullOrEmpty(selectedMatch.Resultat))
            {
                string[] fullTimeGoals = selectedMatch.Resultat.Split(' ')[0].Split('-');
                matchInfo.GoalsFullTimeGSIF = Convert.ToInt32(fullTimeGoals[0]);
                matchInfo.GoalsFullTimeOpponent = Convert.ToInt32(fullTimeGoals[1]);

                string[] halfTimeGoals = selectedMatch.Resultat.Split(' ')[1].Split('-');
                matchInfo.GoalsHalfTimeGSIF = Convert.ToInt32(halfTimeGoals[0].Replace("(", ""));
                matchInfo.GoalsHalfTimeOpponent = Convert.ToInt32(halfTimeGoals[1].Replace(")", ""));
            }

            matchInfo.Time = selectedMatch.Tid;
            matchInfo.WalkOver = string.IsNullOrEmpty(selectedMatch.WO) ? false : true;
            // Få veckodagen på svenska
            matchInfo.WeekDay = System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.DayNames[(int)selectedMatch.Datum.Value.DayOfWeek];
            return matchInfo;
        }

        private List<SelectPlayerItem> SortListAndAddDescriptionText(List<laget_gsif> playerList)
        {
            List<SelectPlayerItem> selectPlayerItemList = new List<SelectPlayerItem>();
            string currentPosition = "-1";
            foreach (laget_gsif player in playerList.OrderBy(p => p.Position).ThenBy(p=>p.FNamn))
            {
                int emptyRowCounter = -100;
                if (player.Position != currentPosition)
                {
                    // Lägg till en tom rad och en rad med utseende <-- Tränare -->
                    currentPosition = player.Position;
                    string positionText = "<-- " + Statuses.GetTextFromDbValue(Position.AllStatuses, currentPosition) + " -->";
                    selectPlayerItemList.Add(new SelectPlayerItem() { Id = emptyRowCounter--, Text = "" });
                    selectPlayerItemList.Add(new SelectPlayerItem() { Id = -1 * Convert.ToInt32(currentPosition), Text = positionText });
                }
                selectPlayerItemList.Add(new SelectPlayerItem(player));
            }

            return selectPlayerItemList;
        }


        [HttpPost]
        public ActionResult UpdateMatchReport(int id, FormCollection collection)
        {
            try
            {
                UpdateMatchReportInDB(id, collection);
            }
            catch (Exception err)
            {
                return View("Error", err);
            }

            return RedirectToAction("Details", new { id = id });
        }

        private void UpdateMatchReportInDB(int id, FormCollection collection)
        {
            int goalsFullTimeGSIF = Convert.ToInt32(collection["Match.GoalsFullTimeGSIF"]);
            int goalsHalfTimeGSIF = Convert.ToInt32(collection["Match.GoalsHalfTimeGSIF"]);
                        
            int goalsFullTimeOpponent = Convert.ToInt32(collection["Match.GoalsFullTimeOpponent"]);
            int goalsHalfTimeOpponent = Convert.ToInt32(collection["Match.GoalsHalfTimeOpponent"]);

            // Kontrollera att halvtidresultat är rimligt med tanke på full tidsresultat
            if (goalsHalfTimeGSIF > goalsFullTimeGSIF || goalsHalfTimeOpponent > goalsFullTimeOpponent)
            {
                throw new Exception("Wrong result");
            }

            // Kontrollera att summan av allas mål och assist inte är större än totalt antal gjorda
            // Kontrollera att samma spelare inte finns med två gånger
            CheckSumGoalsAssAndPlayers(collection, goalsFullTimeGSIF);

            // Kontrollera att hela startelvan har skrivits in?

            // Ta bort all gammal matchstatistik med id
            var existingStats = (from statistics in gsifDB.statistik_gsif
                                 where statistics.StId == id
                                 select statistics).ToList();

            foreach (var existingStat in existingStats)
            {
                gsifDB.statistik_gsif.DeleteObject(existingStat);
            }

            // Uppdatera matchreferat mm
            var match = (from matches in gsifDB.match_gsif
                         where matches.MaId == id
                         select matches).SingleOrDefault();
            if (match == null)
                throw new Exception("Match " + id + " not found");

            match.Resultat = goalsFullTimeGSIF + "-" + goalsFullTimeOpponent +
                " (" + goalsHalfTimeGSIF + "-" + goalsHalfTimeOpponent + ")";
            match.Matchref = collection["Match.MatchReport"];
            match.StatExcist = "Y";

            StatusValue matchType = Statuses.GetStatusFromText(MatchType.AllStatuses, collection["MatchTypeDD"]);
            match.Typ = matchType.DbValue;
            if (matchType == MatchType.League)
                match.Omgang = collection["Match.Round"];
            else
                match.Omgang = "";

            // Lägg upp ny matchstatistik, återanvänd samma id
            foreach (var key in collection.Keys)
            {
                string keyText = key.ToString().ToLower();
                if (keyText.Contains("player") && keyText.Contains('_'))
                {
                    // Spelarinformation. 

                    // Ta ut spelarid och pos. Key är på formatet "Player_id_pos"
                    // Get the new playerId
                    // Hämte värdet på drop downen som är det valda playerId
                    int playerId = Convert.ToInt32(collection[key.ToString()]);
                    if (playerId <= 0)
                        continue; // Hoppa över postioner där ingen spelare är vald

                    string[] keyParts = keyText.Split('_');
                    short pos = Convert.ToInt16(keyParts[2]);

                    bool yellowCard = collection["YellowCard_" + pos].Contains("true");
                    bool redCard = collection["RedCard_" + pos].Contains("true");
                    int goals = Convert.ToInt32(collection["Goals_" + pos]);
                    int assists = Convert.ToInt32(collection["Assists_" + pos]);

                    // Lägg till ny statistik för spelaren
                    statistik_gsif newPlayerStat = new statistik_gsif();
                    newPlayerStat.StId = match.MaId;
                    newPlayerStat.SpId = playerId;
                    newPlayerStat.StType = StatisticType.Match.DbValue;
                    newPlayerStat.Lag = match.Lag;
                    newPlayerStat.Typ = (sbyte)pos;
                    newPlayerStat.Mal = (sbyte)goals;
                    newPlayerStat.Assist = (sbyte)assists;
                    newPlayerStat.Gula = (sbyte)(yellowCard ? 1 : 0);
                    newPlayerStat.Roda = (sbyte)(redCard ? 1 : 0);

                    if (playerId == Convert.ToInt32(collection["ManOfTheMatch"]))
                        newPlayerStat.ManOfMatch = ManOfTheMatch.Yes.DbValue;
                    else
                        newPlayerStat.ManOfMatch = ManOfTheMatch.No.DbValue;

                    gsifDB.statistik_gsif.AddObject(newPlayerStat);
                }
            }

            gsifDB.SaveChanges();

        }

        private static void CheckSumGoalsAssAndPlayers(FormCollection collection, int goalsFullTimeGSIF)
        {
            int totalGoals = 0;
            int totalAssist = 0;
            List<int> choosenPlayerIds = new List<int>();
            foreach (var key in collection.Keys)
            {
                string keyText = key.ToString().ToLower();
                if (keyText.Contains("player") && keyText.Contains('_'))
                {
                    // Spelarinformation. 

                    // Ta ut spelarid och pos. Key är på formatet "Player_id_pos"
                    // Get the new playerId. That is the value of the selected item in the dropdows and that is what the current key points to
                    int playerId = Convert.ToInt32(collection[key.ToString()]);
                    if (choosenPlayerIds.Contains(playerId))
                        throw new Exception("Spelaren finns på mer än en position");

                    // Get position that is part of the key
                    string[] keyParts = keyText.Split('_');
                    short pos = Convert.ToInt16(keyParts[2]);

                    totalGoals += Convert.ToInt32(collection["Goals_" + pos]);
                    totalAssist += Convert.ToInt32(collection["Assists_" + pos]);

                    if (totalGoals > goalsFullTimeGSIF)
                        throw new Exception("Det finns fler mål angivna på spelarna än vad som gjordes i matchen.");

                    if (totalAssist > goalsFullTimeGSIF)
                        throw new Exception("Det finns fler assist angivna på spelarna än vad som gjordes i matchen.");
                }
            }
        }

        public ActionResult AddMatchReport(int id)
        {
            MatchReportSelPositionsViewModel viewModel = new MatchReportSelPositionsViewModel(id);
            return View("AddMatchReport", viewModel);
        }

        [HttpPost]
        [ValidateInput(false)]
        public ActionResult AddMatchReport(int id, FormCollection collection)
        {
            if (collection.AllKeys.Contains("LineUpDD"))
            {
                // Show the form to create a matchreport 

                // ViewModel to return
                MatchReportViewModel matchReportViewModel = new MatchReportViewModel();

                matchReportViewModel.Match = GetMatchInformation(id);

                // Get all Herr or Dam players
                List<SelectPlayerItem> selectPlayerList = new List<SelectPlayerItem>();
                selectPlayerList = GetSelectablePlayers(matchReportViewModel.Match.Team);

                // Loop over all players and set properties on viewmodel for each player
                SetMatchStatisticPerPlayer(id, matchReportViewModel);

                // Loop over each person and add list of potential players to select from and add it to list with man of the match players
                foreach (var matchStatPerson in matchReportViewModel.MatchStatistics)
                {
                    // Skapa en selectList med alla spelare som kan väljas samt sätt denna som förvald
                    matchStatPerson.AllPlayers = new SelectList(selectPlayerList, "Id", "Text", matchStatPerson.PlayerID);
                }

                string lineUp = collection["LineUpDD"];
                if (lineUp.ToLower().Contains("välj"))
                {
                    return View("WrongLineUp");
                }

                matchReportViewModel.MatchStatistics = new List<MatchStatPerson>();

                // Add GoalKeaperPosition
                MatchStatPerson matchStatGolie = new MatchStatPerson();
                matchStatGolie.Position = Convert.ToInt32(Position.GoalKeeper.DbValue + 3);
                matchStatGolie.AllPlayers = new SelectList(selectPlayerList, "Id", "Text", -1 * Convert.ToInt32(Position.GoalKeeper.DbValue));
                matchReportViewModel.MatchStatistics.Add(matchStatGolie);


                // Lägg till övriga positioner nedan
                // Lägg till rätt position. Positionen består av två siffror. Första siffran är grundpositionen, tex forward = 4. Den andra siffran räknas
                // upp för varje forward och börjar på 1. Dvs 41, 42 osv.
                // För varje position läggs även en lista med samtliga valbara spelare till, där default valet är positonnsnamnet

                // Add Defender
                int numberOfDefender = Convert.ToInt32(lineUp[0].ToString());
                for (int i = 0; i < numberOfDefender; i++)
                {
                    MatchStatPerson matchStatDefender = new MatchStatPerson();
                    matchStatDefender.Position = Convert.ToInt32(Position.Defender.DbValue + (i + 1));
                    matchStatDefender.AllPlayers = new SelectList(selectPlayerList, "Id", "Text", -1 * Convert.ToInt32(Position.Defender.DbValue));
                    matchReportViewModel.MatchStatistics.Add(matchStatDefender);
                }

                // Add Midfielder
                int numberOfMidfielders = Convert.ToInt32(lineUp[1].ToString());
                for (int i = 0; i < numberOfMidfielders; i++)
                {
                    MatchStatPerson matchStatMidfielder = new MatchStatPerson();
                    matchStatMidfielder.Position = Convert.ToInt32(Position.Midfielder.DbValue + (i + 1));
                    matchStatMidfielder.AllPlayers = new SelectList(selectPlayerList, "Id", "Text", -1 * Convert.ToInt32(Position.Midfielder.DbValue));
                    matchReportViewModel.MatchStatistics.Add(matchStatMidfielder);
                }

                // Add Forward
                if (lineUp.Length > 2)
                {
                    int numberOfForwards = Convert.ToInt32(lineUp[2].ToString());
                    for (int i = 0; i < numberOfForwards; i++)
                    {
                        MatchStatPerson matchStatForward = new MatchStatPerson();
                        matchStatForward.Position = Convert.ToInt32(Position.Forward.DbValue + (i + 1));
                        matchStatForward.AllPlayers = new SelectList(selectPlayerList, "Id", "Text", -1 * Convert.ToInt32(Position.Forward.DbValue));
                        matchReportViewModel.MatchStatistics.Add(matchStatForward);
                    }
                }

                // Add Substituters
                int numberOfSubstituters = 5;
                for (int i = 0; i < numberOfSubstituters; i++)
                {
                    MatchStatPerson matchStatForward = new MatchStatPerson();
                    matchStatForward.Position = Convert.ToInt32(Position.Substituter.DbValue + (i + 1));
                    matchStatForward.AllPlayers = new SelectList(selectPlayerList, "Id", "Text", -1 * Convert.ToInt32(Position.Defender.DbValue));
                    matchReportViewModel.MatchStatistics.Add(matchStatForward);
                }

                List<SelectPlayerItem> momPlayerList = new List<SelectPlayerItem>();
                momPlayerList.Add(new SelectPlayerItem() { Id = -1, Text = "<-- Välj -->" });

                matchReportViewModel.ManOfMatchPlayers = new SelectList(momPlayerList, "Id", "Text", -1);

                return View("UpdateMatchReport", matchReportViewModel);
            }
            else
            {
                // Matchreport created.
                UpdateMatchReportInDB(id, collection);
                return RedirectToAction("Details", new { id = id });
            }
        }


        
    }
}
